package com.viu.demo.service;

import com.alibaba.fastjson.JSONObject;
import com.sun.mail.imap.protocol.BODY;
import com.viu.TechnologyIntegrationApplication;
import com.viu.technology.controller.OrderController;
import com.viu.technology.po.Order;
import org.apache.tomcat.util.codec.binary.Base64;
import org.databene.contiperf.PerfTest;
import org.databene.contiperf.Required;
import org.databene.contiperf.junit.ContiPerfRule;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.security.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

/*@SpringBootTest
@RunWith(SpringRunner.class)*/
public class test {

    @Autowired
    private OrderController orderController;

    /*@Rule
    public ContiPerfRule i = new ContiPerfRule();*/

    //开启500条线程执行100000万次
    @PerfTest(invocations = 5000,threads = 400)
    //最长使用1200毫秒，平均250，总时长60000
    //@Required(max = 1200, average = 250, totalTime = 60000)
    @Test
    public void test() {

        RestTemplate restTemplate = new RestTemplate();


        Order order = new Order();
        order.setProductId("2832c162f2544ebca276a242fb9878f0");
        order.setProductCount(1);
        order.setAddressId(32);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Authorization", "Bearer eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE1MzQ3NTAxMzksInN1YiI6IjEyMyIsImNyZWF0ZWQiOjE1MzQxNDUzMzk1MTl9.VlPjULHIaW_BdlWYR3VJMstRjDYfNvpn2nUeoFuROqoT0dpFVbrVFS-w9zuPkxc2BoWWVaMStmcgJLvLDpGHhw");

        MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();


        JSONObject jsonObj = JSONObject.parseObject(order.toString());

        HttpEntity<String> formEntity = new HttpEntity<String>(jsonObj.toString(), headers);

        //String result = restTemplate.postForObject("http://localhost:8080/order/generate/pessimism", formEntity, String.class);
        String result = restTemplate.postForObject("http://localhost:8080/order/generate/redis", formEntity, String.class);
        System.out.println(result);

    }

    @Test
    public void test2() {

        RestTemplate restTemplate = new RestTemplate();


        HttpHeaders headers = new HttpHeaders();
        //headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Authorization", "Bearer eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE1MzQ3NTAxMzksInN1YiI6IjEyMyIsImNyZWF0ZWQiOjE1MzQxNDUzMzk1MTl9.VlPjULHIaW_BdlWYR3VJMstRjDYfNvpn2nUeoFuROqoT0dpFVbrVFS-w9zuPkxc2BoWWVaMStmcgJLvLDpGHhw");

        MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();

        String xml = "<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"yes\"?>\n" +
                "<xml>\n" +
                "<curr_type>CNY</curr_type>\n" +
                "<ins_cd>08A9999999</ins_cd>\n" +
                "<mchnt_cd>0002900F0370586</mchnt_cd>\n" +
                "<mchnt_order_no>123456789699072</mchnt_order_no>\n" +
                "<order_amt>200</order_amt>\n" +
                "<order_type>ALIPAY</order_type>\n" +
                "<random_str>6U1YRZ2ZB3PVXKHLEM5PY0LQCZ4S6JQS</random_str>\n" +
                "<reserved_buyer_logon_id></reserved_buyer_logon_id>\n" +
                "<reserved_channel_order_id></reserved_channel_order_id>\n" +
                "<reserved_coupon_fee></reserved_coupon_fee>\n" +
                "<reserved_fund_bill_list></reserved_fund_bill_list>\n" +
                "<reserved_fy_settle_dt>20170801</reserved_fy_settle_dt>\n" +
                "<reserved_fy_trace_no>900000041024</reserved_fy_trace_no>\n" +
                "<result_code>000000</result_code>\n" +
                "<result_msg>SUCCESS</result_msg>\n" +
                "<settle_order_amt>200</settle_order_amt>\n" +
                "<sign>m4iJ+CL9gw+JtOFA04qzqbguKJdsYRiIaEZZGty6ivsqgUww01n/IbejQrjaTyzkup5IFqDlxqYX\n" +
                "66oZT/7SEX/07gLX7xa+3pi/+xxiPyYGt3UI8s/TAjZHr1QB6PrRZ+PUgX9ycUMCXpLqqiEzCDBe\n" +
                "S3HzhQr/Q3uMSNSXfRg=\n" +
                "</sign>\n" +
                "<term_id></term_id>\n" +
                "<transaction_id>2017080121001004850200257332</transaction_id>\n" +
                "<txn_fin_ts>20170801163947</txn_fin_ts>\n" +
                "<user_id>2088102172192852</user_id>\n" +
                "</xml>\n";


        HttpEntity<String> formEntity = new HttpEntity<String>(xml, headers);

        //String result = restTemplate.postForObject("http://localhost:8080/order/generate/pessimism", formEntity, String.class);
        String result = restTemplate.postForObject("http://localhost:8080/pay/notify", formEntity, String.class);
        System.out.println(result);

    }

    @Test
    public void test3() throws Exception {
        /*String xml = "<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"yes\"?>\n" +
                "<xml>\n" +
                "<curr_type>CNY</curr_type>\n" +
                "<ins_cd>08A9999999</ins_cd>\n" +
                "<mchnt_cd>0002900F0370586</mchnt_cd>\n" +
                "<mchnt_order_no>123456789699072</mchnt_order_no>\n" +
                "<order_amt>200</order_amt>\n" +
                "<order_type>ALIPAY</order_type>\n" +
                "<random_str>6U1YRZ2ZB3PVXKHLEM5PY0LQCZ4S6JQS</random_str>\n" +
                "<reserved_buyer_logon_id></reserved_buyer_logon_id>\n" +
                "<reserved_channel_order_id></reserved_channel_order_id>\n" +
                "<reserved_coupon_fee></reserved_coupon_fee>\n" +
                "<reserved_fund_bill_list></reserved_fund_bill_list>\n" +
                "<reserved_fy_settle_dt>20170801</reserved_fy_settle_dt>\n" +
                "<reserved_fy_trace_no>900000041024</reserved_fy_trace_no>\n" +
                "<result_code>000000</result_code>\n" +
                "<result_msg>SUCCESS</result_msg>\n" +
                "<settle_order_amt>200</settle_order_amt>\n" +
                "<sign>m4iJ+CL9gw+JtOFA04qzqbguKJdsYRiIaEZZGty6ivsqgUww01n/IbejQrjaTyzkup5IFqDlxqYX\n" +
                "66oZT/7SEX/07gLX7xa+3pi/+xxiPyYGt3UI8s/TAjZHr1QB6PrRZ+PUgX9ycUMCXpLqqiEzCDBe\n" +
                "S3HzhQr/Q3uMSNSXfRg=\n" +
                "</sign>\n" +
                "<term_id></term_id>\n" +
                "<transaction_id>2017080121001004850200257332</transaction_id>\n" +
                "<txn_fin_ts>20170801163947</txn_fin_ts>\n" +
                "<user_id>2088102172192852</user_id>\n" +
                "</xml>\n";*/
        String xml = "<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"yes\"?>\n" +
                "<xml>\n" +
                "<addn_inf></addn_inf>\n" +
                "<curr_type>CNY</curr_type>\n" +
                "<goods_des>Cold Drink 100ml</goods_des>\n" +
                "<goods_detail>Cold Drink 100ml</goods_detail>\n" +
                "<goods_tag></goods_tag>\n" +
                "<ins_cd>08M0061520</ins_cd>\n" +
                "<mchnt_cd>0002230F0348879</mchnt_cd>\n" +
                "<mchnt_order_no>991501572645</mchnt_order_no>\n" +
                "<notify_url>http://www-1.fuiou.com:28090/gpay/wg/atCallback.fuiou</notify_url>\n" +
                "<order_amt>1</order_amt>\n" +
                "<order_type>ALIPAY</order_type>\n" +
                "<random_str>2059802e25d44a9</random_str>\n" +
                "<sign>oy7XfQzNEInzlt2nfmbyL20pjkXkTcApCq0MbPL3rs0IEkHnDiccJqb9DR68BYYvRKQzZEzUyKyB3YDOoy8hpVFv+a8ht8jGOf9f2oMMfBpz2Ihjv0vp9Zbex1kEhwJmiU1RKY+S8FzXYlW+rCttt51XMu0NQfQlLf0e6ZhVO3c=\n" +
                "</sign>\n" +
                "<term_id></term_id>\n" +
                "<term_ip>115.112.59.162</term_ip>\n" +
                "<txn_begin_ts>20170801152328</txn_begin_ts>\n" +
                "<version>1.0</version>\n" +
                "</xml>\n";

        HashMap<String, String> map = xmlStr2Map(xml);

        System.out.println("========================");
        Map<String, String> testMap2 = new TreeMap<String, String>(map);


        StringBuffer sb = new StringBuffer();
        for (String key : testMap2.keySet()) {

            if (key.startsWith("sign") || key.startsWith("reserved")) {
                continue;
            }
            sb.append(key);
            sb.append("=");
            sb.append(testMap2.get(key));
            sb.append("&");
        }
        String sign=sb.substring(0, sb.length() - 1);
        System.out.println("-----"+sign);

        KeyPair keyPair = getKeyPair();
        PublicKey publicKey =  keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        //String md5Sign  = getMd5Sign(sign.toString(),privateKey);
        String md5Sign = map.get("sign");
        System.out.println("sign with md5 and rsa :"+ sign);
        System.out.println("sign with md5 and rsa :"+ md5Sign);
        boolean md5Verifty = verifyWhenMd5Sign(sign,md5Sign,publicKey);
        System.out.println("verify sign with md5 and rsa :"+ md5Verifty);
    }

    public static HashMap<String,String> xmlStr2Map(String xmlStr){
        HashMap<String,String> map = new HashMap<String,String>();
        Document doc;
        try {
            doc = DocumentHelper.parseText(xmlStr);
            Element root = doc.getRootElement();
            List children = root.elements();
            if(children != null && children.size() > 0) {
                for(int i = 0; i < children.size(); i++) {
                    Element child = (Element)children.get(i);
                    map.put(child.getName(), child.getTextTrim());
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return map;
    }

    //生成密钥对
    static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(1024); //可以理解为：加密后的密文长度，实际原文要小些 越大 加密解密越慢
        KeyPair keyPair = keyGen.generateKeyPair();
        return keyPair;
    }

    //用md5生成内容摘要，再用RSA的私钥加密，进而生成数字签名
    static String getMd5Sign(String content , PrivateKey privateKey) throws Exception {
        byte[] contentBytes = content.getBytes("GBK");
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initSign(privateKey);
        signature.update(contentBytes);
        byte[] signs = signature.sign();
        return Base64.encodeBase64String(signs);
    }

    //对用md5和RSA私钥生成的数字签名进行验证
    static boolean verifyWhenMd5Sign(String content, String sign, PublicKey publicKey) throws Exception {
        byte[] contentBytes = content.getBytes("GBK");
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(publicKey);
        signature.update(contentBytes);
        return signature.verify(Base64.decodeBase64(sign));
    }


}

/*
* samples: 10000
max:     21485
average: 2129.357
median:  856
-
samples: 10000
max:     15218
average: 1204.1613
median:  770
samples: 10000
max:     10063
average: 1318.7869
median:  1436


samples: 10000
max:     13395
average: 2294.1854
median:  2354
-
samples: 10000
max:     6728
average: 1382.5879
median:  1377
* */
